home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-17 / herkules.zip / HERKULES.INC < prev   
Text File  |  1989-10-30  |  49KB  |  1,044 lines

  1. ;+---------------------------------------------------------------------------+
  2. ;!                             IncludeFile zu                                !
  3. ;!                              HERKULES.ASM                                 !
  4. ;+---------------------------------------------------------------------------+
  5. ;Hier zuerst die ZeichenSatz-Tabelle:
  6.   DB 000h,000h,000h,000h,000h,000h,000h,000h
  7.   DB 07Eh,081h,0A5h,081h,0BDh,099h,081h,07Eh
  8.   DB 07Eh,0FFh,0DBh,0FFh,0C3h,0E7h,0FFh,07Eh
  9.   DB 06Ch,0FEh,0FEh,0FEh,07Ch,038h,010h,000h
  10.   DB 010h,038h,07Ch,0FEh,07Ch,038h,010h,000h
  11.   DB 038h,07Ch,038h,0FEh,0FEh,07Ch,038h,07Ch
  12.   DB 010h,010h,038h,07Ch,0FEh,07Ch,038h,07Ch
  13.   DB 000h,000h,018h,03Ch,03Ch,018h,000h,000h
  14.   DB 0FFh,0FFh,0E7h,0C3h,0C3h,0E7h,0FFh,0FFh
  15.   DB 000h,03Ch,066h,042h,042h,066h,03Ch,000h
  16.   DB 0FFh,0C3h,099h,0BDh,0BDh,099h,0C3h,0FFh
  17.   DB 00Fh,007h,00Fh,07Dh,0CCh,0CCh,0CCh,078h
  18.   DB 03Ch,066h,066h,066h,03Ch,018h,07Eh,018h
  19.   DB 03Fh,033h,03Fh,030h,030h,070h,0F0h,0E0h
  20.   DB 07Fh,063h,07Fh,063h,063h,067h,0E6h,0C0h
  21.   DB 099h,05Ah,03Ch,0E7h,0E7h,03Ch,05Ah,099h
  22.   DB 080h,0E0h,0F8h,0FEh,0F8h,0E0h,080h,000h
  23.   DB 002h,00Eh,03Eh,0FEh,03Eh,00Eh,002h,000h
  24.   DB 018h,03Ch,07Eh,018h,018h,07Eh,03Ch,018h
  25.   DB 066h,066h,066h,066h,066h,000h,066h,000h
  26.   DB 07Fh,0DBh,0DBh,07Bh,01Bh,01Bh,01Bh,000h
  27.   DB 03Eh,063h,038h,06Ch,06Ch,038h,0CCh,078h
  28.   DB 000h,000h,000h,000h,07Eh,07Eh,07Eh,000h
  29.   DB 018h,03Ch,07Eh,018h,07Eh,03Ch,018h,0FFh
  30.   DB 018h,03Ch,07Eh,018h,018h,018h,018h,000h
  31.   DB 018h,018h,018h,018h,07Eh,03Ch,018h,000h
  32.   DB 000h,018h,00Ch,0FEh,00Ch,018h,000h,000h
  33.   DB 000h,030h,060h,0FEh,060h,030h,000h,000h
  34.   DB 000h,000h,0C0h,0C0h,0C0h,0FEh,000h,000h
  35.   DB 000h,024h,066h,0FFh,066h,024h,000h,000h
  36.   DB 000h,018h,03Ch,07Eh,0FFh,0FFh,000h,000h
  37.   DB 000h,0FFh,0FFh,07Eh,03Ch,018h,000h,000h
  38.   DB 000h,000h,000h,000h,000h,000h,000h,000h
  39.   DB 030h,078h,078h,078h,030h,000h,030h,000h
  40.   DB 06Ch,06Ch,06Ch,000h,000h,000h,000h,000h
  41.   DB 06Ch,06Ch,0FEh,06Ch,0FEh,06Ch,06Ch,000h
  42.   DB 030h,07Ch,0C0h,078h,00Ch,0F8h,030h,000h
  43.   DB 000h,0C6h,0CCh,018h,030h,066h,0C6h,000h
  44.   DB 038h,06Ch,038h,076h,0DCh,0CCh,076h,000h
  45.   DB 060h,060h,0C0h,000h,000h,000h,000h,000h
  46.   DB 018h,030h,060h,060h,060h,030h,018h,000h
  47.   DB 060h,030h,018h,018h,018h,030h,060h,000h
  48.   DB 000h,066h,03Ch,0FFh,03Ch,066h,000h,000h
  49.   DB 000h,030h,030h,0FCh,030h,030h,000h,000h
  50.   DB 000h,000h,000h,000h,000h,030h,030h,060h
  51.   DB 000h,000h,000h,0FCh,000h,000h,000h,000h
  52.   DB 000h,000h,000h,000h,000h,030h,030h,000h
  53.   DB 006h,00Ch,018h,030h,060h,0C0h,080h,000h
  54.   DB 07Ch,0C6h,0CEh,0DEh,0F6h,0E6h,07Ch,000h
  55.   DB 030h,070h,030h,030h,030h,030h,0FCh,000h
  56.   DB 078h,0CCh,00Ch,038h,060h,0CCh,0FCh,000h
  57.   DB 078h,0CCh,00Ch,038h,00Ch,0CCh,078h,000h
  58.   DB 01Ch,03Ch,06Ch,0CCh,0FEh,00Ch,01Eh,000h
  59.   DB 0FCh,0C0h,0F8h,00Ch,00Ch,0CCh,078h,000h
  60.   DB 038h,060h,0C0h,0F8h,0CCh,0CCh,078h,000h
  61.   DB 0FCh,0CCh,00Ch,018h,030h,030h,030h,000h
  62.   DB 078h,0CCh,0CCh,078h,0CCh,0CCh,078h,000h
  63.   DB 078h,0CCh,0CCh,07Ch,00Ch,018h,070h,000h
  64.   DB 000h,030h,030h,000h,000h,030h,030h,000h
  65.   DB 000h,030h,030h,000h,000h,030h,030h,060h
  66.   DB 018h,030h,060h,0C0h,060h,030h,018h,000h
  67.   DB 000h,000h,0FCh,000h,000h,0FCh,000h,000h
  68.   DB 060h,030h,018h,00Ch,018h,030h,060h,000h
  69.   DB 078h,0CCh,00Ch,018h,030h,000h,030h,000h
  70.   DB 07Ch,0C6h,0DEh,0DEh,0DEh,0C0h,078h,000h
  71.   DB 030h,078h,0CCh,0CCh,0FCh,0CCh,0CCh,000h
  72.   DB 0FCh,066h,066h,07Ch,066h,066h,0FCh,000h
  73.   DB 03Ch,066h,0C0h,0C0h,0C0h,066h,03Ch,000h
  74.   DB 0F8h,06Ch,066h,066h,066h,06Ch,0F8h,000h
  75.   DB 07Eh,060h,060h,078h,060h,060h,07Eh,000h
  76.   DB 07Eh,060h,060h,078h,060h,060h,060h,000h
  77.   DB 03Ch,066h,0C0h,0C0h,0CEh,066h,03Eh,000h
  78.   DB 0CCh,0CCh,0CCh,0FCh,0CCh,0CCh,0CCh,000h
  79.   DB 078h,030h,030h,030h,030h,030h,078h,000h
  80.   DB 01Eh,00Ch,00Ch,00Ch,0CCh,0CCh,078h,000h
  81.   DB 0E6h,066h,06Ch,078h,06Ch,066h,0E6h,000h
  82.   DB 060h,060h,060h,060h,060h,060h,07Eh,000h
  83.   DB 0C6h,0EEh,0FEh,0FEh,0D6h,0C6h,0C6h,000h
  84.   DB 0C6h,0E6h,0F6h,0DEh,0CEh,0C6h,0C6h,000h
  85.   DB 038h,06Ch,0C6h,0C6h,0C6h,06Ch,038h,000h
  86.   DB 0FCh,066h,066h,07Ch,060h,060h,0F0h,000h
  87.   DB 078h,0CCh,0CCh,0CCh,0DCh,078h,01Ch,000h
  88.   DB 0FCh,066h,066h,07Ch,06Ch,066h,0E6h,000h
  89.   DB 078h,0CCh,0E0h,070h,01Ch,0CCh,078h,000h
  90.   DB 0FCh,030h,030h,030h,030h,030h,030h,000h
  91.   DB 0CCh,0CCh,0CCh,0CCh,0CCh,0CCh,0FCh,000h
  92.   DB 0CCh,0CCh,0CCh,0CCh,0CCh,078h,030h,000h
  93.   DB 0C6h,0C6h,0C6h,0D6h,0FEh,0EEh,0C6h,000h
  94.   DB 0C6h,0C6h,06Ch,038h,038h,06Ch,0C6h,000h
  95.   DB 0CCh,0CCh,0CCh,078h,030h,030h,078h,000h
  96.   DB 0FEh,006h,00Ch,018h,030h,060h,0FEh,000h
  97.   DB 078h,060h,060h,060h,060h,060h,078h,000h
  98.   DB 0C0h,060h,030h,018h,00Ch,006h,002h,000h
  99.   DB 078h,018h,018h,018h,018h,018h,078h,000h
  100.   DB 010h,038h,06Ch,0C6h,000h,000h,000h,000h
  101.   DB 000h,000h,000h,000h,000h,000h,000h,0FFh
  102.   DB 030h,030h,018h,000h,000h,000h,000h,000h
  103.   DB 000h,000h,078h,00Ch,07Ch,0CCh,076h,000h
  104.   DB 0E0h,060h,060h,07Ch,066h,066h,0DCh,000h
  105.   DB 000h,000h,078h,0CCh,0C0h,0CCh,078h,000h
  106.   DB 01Ch,00Ch,00Ch,07Ch,0CCh,0CCh,076h,000h
  107.   DB 000h,000h,078h,0CCh,0FCh,0C0h,078h,000h
  108.   DB 038h,06Ch,060h,0F0h,060h,060h,0F0h,000h
  109.   DB 000h,000h,076h,0CCh,0CCh,07Ch,00Ch,0F8h
  110.   DB 0E0h,060h,06Ch,076h,066h,066h,0E6h,000h
  111.   DB 030h,000h,070h,030h,030h,030h,078h,000h
  112.   DB 00Ch,000h,00Ch,00Ch,00Ch,0CCh,0CCh,078h
  113.   DB 0E0h,060h,066h,06Ch,078h,06Ch,0E6h,000h
  114.   DB 070h,030h,030h,030h,030h,030h,078h,000h
  115.   DB 000h,000h,0CCh,0FEh,0FEh,0D6h,0C6h,000h
  116.   DB 000h,000h,0F8h,0CCh,0CCh,0CCh,0CCh,000h
  117.   DB 000h,000h,078h,0CCh,0CCh,0CCh,078h,000h
  118.   DB 000h,000h,0DCh,066h,066h,07Ch,060h,0F0h
  119.   DB 000h,000h,076h,0CCh,0CCh,07Ch,00Ch,01Eh
  120.   DB 000h,000h,0DCh,076h,066h,060h,0F0h,000h
  121.   DB 000h,000h,07Ch,0C0h,078h,00Ch,0F8h,000h
  122.   DB 010h,030h,07Ch,030h,030h,034h,018h,000h
  123.   DB 000h,000h,0CCh,0CCh,0CCh,0CCh,076h,000h
  124.   DB 000h,000h,0CCh,0CCh,0CCh,078h,030h,000h
  125.   DB 000h,000h,0C6h,0D6h,0FEh,0FEh,06Ch,000h
  126.   DB 000h,000h,0C6h,06Ch,038h,06Ch,0C6h,000h
  127.   DB 000h,000h,0CCh,0CCh,0CCh,07Ch,00Ch,0F8h
  128.   DB 000h,000h,0FCh,098h,030h,064h,0FCh,000h
  129.   DB 01Ch,030h,030h,0E0h,030h,030h,01Ch,000h
  130.   DB 018h,018h,018h,000h,018h,018h,018h,000h
  131.   DB 0E0h,030h,030h,01Ch,030h,030h,0E0h,000h
  132.   DB 076h,0DCh,000h,000h,000h,000h,000h,000h
  133.   DB 000h,010h,038h,06Ch,0C6h,0C6h,0FEh,000h
  134.   DB 078h,0CCh,0C0h,0CCh,078h,018h,00Ch,078h
  135.   DB 000h,0CCh,000h,0CCh,0CCh,0CCh,07Eh,000h
  136.   DB 01Ch,000h,078h,0CCh,0FCh,0C0h,078h,000h
  137.   DB 07Eh,0C3h,03Ch,006h,03Eh,066h,03Fh,000h
  138.   DB 0CCh,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
  139.   DB 0E0h,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
  140.   DB 030h,030h,078h,00Ch,07Ch,0CCh,07Eh,000h
  141.   DB 000h,000h,078h,0C0h,0C0h,078h,00Ch,038h
  142.   DB 07Eh,0C3h,03Ch,066h,07Eh,060h,03Ch,000h
  143.   DB 0CCh,000h,078h,0CCh,0FCh,0C0h,078h,000h
  144.   DB 0E0h,000h,078h,0CCh,0FCh,0C0h,078h,000h
  145.   DB 0CCh,000h,070h,030h,030h,030h,078h,000h
  146.   DB 07Ch,0C6h,038h,018h,018h,018h,03Ch,000h
  147.   DB 0E0h,000h,070h,030h,030h,030h,078h,000h
  148.   DB 0C6h,038h,06Ch,0C6h,0FEh,0C6h,0C6h,000h
  149.   DB 030h,030h,000h,078h,0CCh,0FCh,0CCh,000h
  150.   DB 01Ch,000h,0FCh,060h,078h,060h,0FCh,000h
  151.   DB 000h,000h,07Fh,00Ch,07Fh,0CCh,07Fh,000h
  152.   DB 03Eh,06Ch,0CCh,0FEh,0CCh,0CCh,0CEh,000h
  153.   DB 078h,0CCh,000h,078h,0CCh,0CCh,078h,000h
  154.   DB 000h,0CCh,000h,078h,0CCh,0CCh,078h,000h
  155.   DB 000h,0E0h,000h,078h,0CCh,0CCh,078h,000h
  156.   DB 078h,0CCh,000h,0CCh,0CCh,0CCh,07Eh,000h
  157.   DB 000h,0E0h,000h,0CCh,0CCh,0CCh,07Eh,000h
  158.   DB 000h,0CCh,000h,0CCh,0CCh,07Ch,00Ch,0F8h
  159.   DB 0C3h,018h,03Ch,066h,066h,03Ch,018h,000h
  160.   DB 0CCh,000h,0CCh,0CCh,0CCh,0CCh,078h,000h
  161.   DB 018h,018h,07Eh,0C0h,0C0h,07Eh,018h,018h
  162.   DB 038h,06Ch,064h,0F0h,060h,0E6h,0FCh,000h
  163.   DB 0CCh,0CCh,078h,0FCh,030h,0FCh,030h,030h
  164.   DB 0F8h,0CCh,0CCh,0FAh,0C6h,0CFh,0C6h,0C7h
  165.   DB 00Eh,01Bh,018h,03Ch,018h,018h,0D8h,070h
  166.   DB 01Ch,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
  167.   DB 038h,000h,070h,030h,030h,030h,078h,000h
  168.   DB 000h,01Ch,000h,078h,0CCh,0CCh,078h,000h
  169.   DB 000h,01Ch,000h,0CCh,0CCh,0CCh,07Eh,000h
  170.   DB 000h,0F8h,000h,0F8h,0CCh,0CCh,0CCh,000h
  171.   DB 0FCh,000h,0CCh,0ECh,0FCh,0DCh,0CCh,000h
  172.   DB 03Ch,06Ch,06Ch,03Eh,000h,07Eh,000h,000h
  173.   DB 038h,06Ch,06Ch,038h,000h,07Ch,000h,000h
  174.   DB 030h,000h,030h,060h,0C0h,0CCh,078h,000h
  175.   DB 000h,000h,000h,0FCh,0C0h,0C0h,000h,000h
  176.   DB 000h,000h,000h,0FCh,00Ch,00Ch,000h,000h
  177.   DB 0C3h,0C6h,0CCh,0DEh,033h,066h,0CCh,00Fh
  178.   DB 0C3h,0C6h,0CCh,0DBh,037h,06Fh,0CFh,003h
  179.   DB 018h,018h,000h,018h,018h,018h,018h,000h
  180.   DB 000h,033h,066h,0CCh,066h,033h,000h,000h
  181.   DB 000h,0CCh,066h,033h,066h,0CCh,000h,000h
  182.   DB 022h,088h,022h,088h,022h,088h,022h,088h
  183.   DB 055h,0AAh,055h,0AAh,055h,0AAh,055h,0AAh
  184.   DB 0DBh,077h,0DBh,0EEh,0DBh,077h,0DBh,0EEh
  185.   DB 018h,018h,018h,018h,018h,018h,018h,018h
  186.   DB 018h,018h,018h,018h,0F8h,018h,018h,018h
  187.   DB 018h,018h,0F8h,018h,0F8h,018h,018h,018h
  188.   DB 036h,036h,036h,036h,0F6h,036h,036h,036h
  189.   DB 000h,000h,000h,000h,0FEh,036h,036h,036h
  190.   DB 000h,000h,0F8h,018h,0F8h,018h,018h,018h
  191.   DB 036h,036h,0F6h,006h,0F6h,036h,036h,036h
  192.   DB 036h,036h,036h,036h,036h,036h,036h,036h
  193.   DB 000h,000h,0FEh,006h,0F6h,036h,036h,036h
  194.   DB 036h,036h,0F6h,006h,0FEh,000h,000h,000h
  195.   DB 036h,036h,036h,036h,0FEh,000h,000h,000h
  196.   DB 018h,018h,0F8h,018h,0F8h,000h,000h,000h
  197.   DB 000h,000h,000h,000h,0F8h,018h,018h,018h
  198.   DB 018h,018h,018h,018h,01Fh,000h,000h,000h
  199.   DB 018h,018h,018h,018h,0FFh,000h,000h,000h
  200.   DB 000h,000h,000h,000h,0FFh,018h,018h,018h
  201.   DB 018h,018h,018h,018h,01Fh,018h,018h,018h
  202.   DB 000h,000h,000h,000h,0FFh,000h,000h,000h
  203.   DB 018h,018h,018h,018h,0FFh,018h,018h,018h
  204.   DB 018h,018h,01Fh,018h,01Fh,018h,018h,018h
  205.   DB 036h,036h,036h,036h,037h,036h,036h,036h
  206.   DB 036h,036h,037h,030h,03Fh,000h,000h,000h
  207.   DB 000h,000h,03Fh,030h,037h,036h,036h,036h
  208.   DB 036h,036h,0F7h,000h,0FFh,000h,000h,000h
  209.   DB 000h,000h,0FFh,000h,0F7h,036h,036h,036h
  210.   DB 036h,036h,037h,030h,037h,036h,036h,036h
  211.   DB 000h,000h,0FFh,000h,0FFh,000h,000h,000h
  212.   DB 036h,036h,0F7h,000h,0F7h,036h,036h,036h
  213.   DB 018h,018h,0FFh,000h,0FFh,000h,000h,000h
  214.   DB 036h,036h,036h,036h,0FFh,000h,000h,000h
  215.   DB 000h,000h,0FFh,000h,0FFh,018h,018h,018h
  216.   DB 000h,000h,000h,000h,0FFh,036h,036h,036h
  217.   DB 036h,036h,036h,036h,03Fh,000h,000h,000h
  218.   DB 018h,018h,01Fh,018h,01Fh,000h,000h,000h
  219.   DB 000h,000h,01Fh,018h,01Fh,018h,018h,018h
  220.   DB 000h,000h,000h,000h,03Fh,036h,036h,036h
  221.   DB 036h,036h,036h,036h,0FFh,036h,036h,036h
  222.   DB 018h,018h,0FFh,018h,0FFh,018h,018h,018h
  223.   DB 018h,018h,018h,018h,0F8h,000h,000h,000h
  224.   DB 000h,000h,000h,000h,01Fh,018h,018h,018h
  225.   DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
  226.   DB 000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh
  227.   DB 0F0h,0F0h,0F0h,0F0h,0F0h,0F0h,0F0h,0F0h
  228.   DB 00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh
  229.   DB 0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h
  230.   DB 000h,000h,076h,0DCh,0C8h,0DCh,076h,000h
  231.   DB 000h,078h,0CCh,0F8h,0CCh,0F8h,0C0h,0C0h
  232.   DB 000h,0FCh,0CCh,0C0h,0C0h,0C0h,0C0h,000h
  233.   DB 000h,0FEh,06Ch,06Ch,06Ch,06Ch,06Ch,000h
  234.   DB 0FCh,0CCh,060h,030h,060h,0CCh,0FCh,000h
  235.   DB 000h,000h,07Eh,0D8h,0D8h,0D8h,070h,000h
  236.   DB 000h,066h,066h,066h,066h,07Ch,060h,0C0h
  237.   DB 000h,076h,0DCh,018h,018h,018h,018h,000h
  238.   DB 0FCh,030h,078h,0CCh,0CCh,078h,030h,0FCh
  239.   DB 038h,06Ch,0C6h,0FEh,0C6h,06Ch,038h,000h
  240.   DB 038h,06Ch,0C6h,0C6h,06Ch,06Ch,0EEh,000h
  241.   DB 01Ch,030h,018h,07Ch,0CCh,0CCh,078h,000h
  242.   DB 000h,000h,07Eh,0DBh,0DBh,07Eh,000h,000h
  243.   DB 006h,00Ch,07Eh,0DBh,0DBh,07Eh,060h,0C0h
  244.   DB 038h,060h,0C0h,0F8h,0C0h,060h,038h,000h
  245.   DB 078h,0CCh,0CCh,0CCh,0CCh,0CCh,0CCh,000h
  246.   DB 000h,0FCh,000h,0FCh,000h,0FCh,000h,000h
  247.   DB 030h,030h,0FCh,030h,030h,000h,0FCh,000h
  248.   DB 060h,030h,018h,030h,060h,000h,0FCh,000h
  249.   DB 018h,030h,060h,030h,018h,000h,0FCh,000h
  250.   DB 00Eh,01Bh,01Bh,018h,018h,018h,018h,018h
  251.   DB 018h,018h,018h,018h,018h,0D8h,0D8h,070h
  252.   DB 030h,030h,000h,0FCh,000h,030h,030h,000h
  253.   DB 000h,076h,0DCh,000h,076h,0DCh,000h,000h
  254.   DB 038h,06Ch,06Ch,038h,000h,000h,000h,000h
  255.   DB 000h,000h,000h,018h,018h,000h,000h,000h
  256.   DB 000h,000h,000h,000h,018h,000h,000h,000h
  257.   DB 00Fh,00Ch,00Ch,00Ch,0ECh,06Ch,03Ch,01Ch
  258.   DB 078h,06Ch,06Ch,06Ch,06Ch,000h,000h,000h
  259.   DB 070h,018h,030h,060h,078h,000h,000h,000h
  260.   DB 000h,000h,03Ch,03Ch,03Ch,03Ch,000h,000h
  261.   DB 000h,000h,000h,000h,000h,000h,000h,000h
  262.  
  263. ;----------------------------------------------------------------------------+
  264.  
  265. Debugging = 0
  266.  
  267. @BreakPoint MACRO
  268.   IFE Debugging
  269.     Debugging = 1
  270.     IF1
  271.       %OUT *** Debugging activated ***
  272.     ENDIF
  273.   ENDIF
  274.   call BreakPoint
  275. ENDM
  276.  
  277. @MarkOn MACRO
  278.   IFE Debugging
  279.     Debugging = 1
  280.     IF1
  281.       %OUT *** Debugging activated ***
  282.     ENDIF
  283.   ENDIF
  284.   call MarkOn
  285. ENDM
  286.  
  287. @MarkOff MACRO
  288.   IFE Debugging
  289.     Debugging = 1
  290.     IF1
  291.       %OUT *** Debugging activated ***
  292.     ENDIF
  293.   ENDIF
  294.   call MarkOff
  295. ENDM
  296.  
  297. ;----------------------------------------------------------------------------+
  298.  
  299. ComputeWrapPos MACRO PointerReg  ;DL=BytesToMove.
  300.   LOCAL NoWrapping,GotWrapPos
  301.   mov  ah,dl
  302.   mov  cx,2000h
  303.   sub  cx,PointerReg                               ;CX = Distanz bis zum Wrap.
  304.   test ch,ch                                            ;Distanz >= 256 Bytes?
  305.   jnz  NoWrapping                               ;=> In dieser Zeile kein Wrap.
  306.   cmp  cl,dl                                         ;Distanz >= BytesToMove?
  307.   jb   GotWrapPos                                   ;Dann ebenfalls kein Wrap.
  308. NoWrapping:
  309.   mov  cl,dl                                                   ;In diesem Fall
  310.   mov  ch,0                                            ;CX=ganze Window-Zeile.
  311. GotWrapPos:
  312.   sub  ah,cl                                  ;Wieviel bleibt dann noch übrig?
  313. ENDM  ;CX=Anz MOVSB's vor dem Page-Wrap, AH=Anz dannach.
  314.  
  315. UpdateCursorPos PROC NEAR  ;AX=CursorPos, wird direkt in den Chip geschickt.
  316.   push dx                                                    ;Register retten.
  317.   mov  dx,ax
  318.   DisplayAdress_Text dl,dh
  319.   push ax                                              ;DisplayAdresse merken.
  320.   mov  dx,IndexReg
  321.   mov  al,15
  322.   out  dx,al                                                    ;Select Reg 15
  323.   inc  dx
  324.   pop  ax                                          ;DisplayAdresse zurückholen
  325.   out  dx,al                                           ;und Low Byte schreiben
  326.   dec  dx
  327.   mov  al,14
  328.   out  dx,al                                                    ;Select Reg 14
  329.   inc  dx
  330.   mov  al,ah
  331.   out  dx,al                                         ;und High Byte schreiben.
  332.   pop  dx
  333.   ret
  334. UpdateCursorPos ENDP  ;AX destroyed.
  335.  
  336. UpdateDispStart PROC NEAR  ;AX=neuer DispStart, DS=40h
  337.   mov  CurDispStart,ax
  338.   push dx
  339.   shr  ax,1                                         ;Offset in Words berechnen
  340.   push ax                                                         ;und merken.
  341.   mov  dx,IndexReg
  342.   mov  al,13
  343.   out  dx,al                                          ;RegisterNr ins IndexReg
  344.   inc  dx
  345.   pop  ax                                             ;DisplayPosition nach AX
  346.   out  dx,al                                         ;und LowByte ins DataReg.
  347.   dec  dx
  348.   mov  al,12                                           ;HighByte: Zuerst RegNr
  349.   out  dx,al                                                     ;ins IndexReg
  350.   inc  dx
  351.   mov  al,ah                                           ;und dann das DatenByte
  352.   out  dx,al                                                     ;ins DataReg.
  353.   pop  dx
  354.   ret
  355. UpdateDispStart ENDP  ;AX destroyed
  356.  
  357. ScrollPartOfScreenUp PROC NEAR
  358.   ;AL=NrOfLines, (CH/CL)-(DH/DL), BL=New Attribute, AH=CurVideoMode, BH=PageNr
  359.   push cx                                                    ;Register retten.
  360.   push dx
  361.   push bx
  362.   sub  dx,cx                                           ;WindowGröße berechnen.
  363.   add  dx,0101h
  364.   cmp  al,0                               ;NrOfLines=0?  =>  Window soll nicht
  365.   je   NowClearWindow                     ;gescrolled sondern gelöscht werden.
  366.   cmp  al,dh                                              ;NrOfLines>=WinSize?
  367.   jae  NowClearWindow                          ;Dann das ganze Window löschen.
  368.   mov  bl,al
  369.   cmp  ah,7                                            ;Sind wir im Text-Mode?
  370.   je   DoScrolling0                                   ;Dann ist es ja einfach.
  371.   cmp  cs:FastScrollFlag,True           ;Soll IMMER langsam gescrolled werden?
  372.   jne  DoScrolling0                                          ;Auch in Ordnung.
  373.   mov  al,dl                             ;Wieviele Zeichen enthält das Window,
  374.   mul  dh                                         ;das gescrolled werden soll?
  375.   cmp  ax,WholeScr*2/3                    ;Weniger als 2/3 des ganzen Screens?
  376.   jb   DoScrolling0                           ;Dann ebenfalls direkt scrollen.
  377.   nop                          ;Es soll also FastScrolling gemacht werden. Ok!
  378.   add  ch,dh                              ;(YPos ist für alle Bereiche gleich,
  379.   push cx                                       ;nämlich die erste Zeile unter
  380.   push dx                                       ;dem zu scrollenden Window...)
  381.   mov  dl,cl
  382.   mov  cl,0
  383.   mov  dh,NrOfLines
  384.   call RotateWindowDown                                            ;Bereich 2,
  385.   mov  cl,dl
  386.   pop  dx
  387.   neg  dh
  388.   add  dh,NrOfLines
  389.   add  dh,bl
  390.   call RotateWindowDown                                         ;Bereich 3 und
  391.   add  cl,dl
  392.   mov  dl,NrOfChars
  393.   sub  dl,cl
  394.   mov  dh,NrOfLines
  395.   call RotateWindowDown                   ;Bereich 4 entgegengesetzt rotieren.
  396.   test bh,1
  397.   GetPageArrayIndex OFFSET(DispStartTable),si         ;Um welche Page geht es?
  398.   mov  ax,cs:[si]
  399.   add  ax,2*NrOfChars                                ;Entsprechenden DispStart
  400.   and  ax,1FFFh                                   ;um 2 Scans (je 4 Dots hoch)
  401.   mov  cs:[si],ax                                              ;hochsetzen und
  402.   cmp  bh,ActivePage
  403.   jne  NoDisplayUpdate0                     ;Wurde die active Page gescrolled?
  404.   call UpdateDispStart         ;Dann neue DispStart auch an den 6845 schicken.
  405. NoDisplayUpdate0:
  406.   pop  ax
  407.   mov  cl,al                                         ;Alte XPosLo wiederholen,
  408.   sub  ch,bl           ;CH = YPosLo der nach Einscrollen zu löschenden Zeilen.
  409.   neg  dl
  410.   add  dl,NrOfChars                      ;(DH/DL) = Größe des nach Einscrollen
  411.   sub  dl,cl                                          ;zu löschenden Bereichs.
  412.   mov  dh,bl
  413.   jmp  SHORT NowClearWindow
  414. DoScrolling0:  ;BL=NrOfLines, (CH/CL)=Upper Left, (DH/DL)=Size of Window
  415.   call RotateWindowUp
  416.   add  ch,dh       ;Die neu eingescrollten Zeilen müssen noch gelöscht werden,
  417.   sub  ch,bl         ;und zwar vom unteren Ende des zu scrollenden Bereichs an
  418.   mov  dh,bl                ;so viele Zeilen, wie das Window gescrolled wurde.
  419. NowClearWindow:   ;CX=WindowStart, DX=WindowSize
  420.   pop  bx                                        ;"NewAttrib" und "PageNr" für
  421.   call ClearWindow                                 ;"ClearWindow" zurückholen.
  422.   pop  dx
  423.   pop  cx
  424.   ret
  425. ScrollPartOfScreenUp ENDP  ;AX and SI destroyed.
  426.  
  427. ScrollPartOfScreenDown PROC NEAR
  428.   ;AL=NrOfLines, (CH/CL)-(DH/DL), BL=New Attribute, AH=CurVideoMode, BH=PageNr
  429.   push cx                                                    ;Register retten.
  430.   push dx
  431.   push bx
  432.   sub  dx,cx                                           ;WindowGröße berechnen.
  433.   add  dx,0101h
  434.   cmp  al,0                               ;NrOfLines=0?  =>  Window soll nicht
  435.   je   NowClearWindow                     ;gescrolled sondern gelöscht werden.
  436.   cmp  al,dh                                              ;NrOfLines>=WinSize?
  437.   jae  NowClearWindow                          ;Dann das ganze Window löschen.
  438.   mov  bl,al
  439.   cmp  ah,7                                            ;Sind wir im Text-Mode?
  440.   je   DoScrolling1                                   ;Dann ist es ja einfach.
  441.   cmp  cs:FastScrollFlag,True           ;Soll IMMER langsam gescrolled werden?
  442.   jne  DoScrolling1                                          ;Auch in Ordnung.
  443.   mov  al,dl                             ;Wieviele Zeichen enthält das Window,
  444.   mul  dh                                         ;das gescrolled werden soll?
  445.   cmp  ax,WholeScr*2/3                    ;Weniger als 2/3 des ganzen Screens?
  446.   jb   DoScrolling1                           ;Dann ebenfalls direkt scrollen.
  447.   nop
  448.   add  ch,dh                   ;Es soll also FastScrolling gemacht werden. Ok!
  449.   sub  ch,bl                           ;(YPos ist für alle Bereiche gleich...)
  450.   push dx
  451.   add  cl,dl
  452.   mov  dl,NrOfChars
  453.   sub  dl,cl
  454.   mov  dh,NrOfLines
  455.   call RotateWindowUp                                              ;Bereich 4,
  456.   pop  dx
  457.   push dx
  458.   sub  cl,dl
  459.   neg  dh
  460.   add  dh,NrOfLines
  461.   add  dh,bl
  462.   call RotateWindowUp                                           ;Bereich 3 und
  463.   mov  dl,cl
  464.   mov  cl,0
  465.   mov  dh,NrOfLines
  466.   call RotateWindowUp                     ;Bereich 2 entgegengesetzt rotieren.
  467.   test bh,1
  468.   GetPageArrayIndex OFFSET(DispStartTable),si         ;Um welche Page geht es?
  469.   mov  ax,cs:[si]
  470.   sub  ax,2*NrOfChars                                ;Entsprechenden DispStart
  471.   and  ax,1FFFh                                   ;um 2 Scans (je 4 Dots hoch)
  472.   mov  cs:[si],ax                                            ;zurücksetzen und
  473.   cmp  bh,ActivePage
  474.   jne  NoDisplayUpdate1                     ;Wurde die active Page gescrolled?
  475.   call UpdateDispStart         ;Dann neue DispStart auch an den 6845 schicken.
  476. NoDisplayUpdate1:
  477.   mov  cl,dl
  478.   pop  dx                                                   ;(CL/CH) - (DL/DH)
  479.   sub  ch,dh
  480.   add  ch,bl                                          ; = nach dem Einscrollen
  481.   mov  dh,bl                                           ;zu löschender Bereich.
  482.   jmp  NowClearWindow
  483. DoScrolling1:  ;BL=NrOfLines, (CH/CL)=Upper Left, (DH/DL)=Size of Window
  484.   call RotateWindowDown
  485.   mov  dh,bl                               ;Die oben neu eingescrollten Zeilen
  486.   jmp  NowClearWindow                            ;müssen noch gelöscht werden.
  487. ScrollPartOfScreenDown ENDP  ;AX and SI destroyed.
  488.  
  489. RotParamCheck PROC NEAR
  490.   cmp  dh,1                             ;Sollen 0 oder 1 Zeile rotiert werden?
  491.   jbe  NoRotation                        ;Brauchen wir gar nicht mit anfangen.
  492.   cmp  dl,0                                         ;Ist das Window so schmal?
  493.   je   NoRotation                                 ;Dann sind wir schon fertig.
  494.   mov  al,bl
  495. RangeParam:
  496.   sub  al,dh             ;Soll das Window um mehr Zeilen rotiert werden als es
  497.   ja   RangeParam         ;hoch ist? Dann BL in den richtigen Bereich bringen.
  498.   add  al,dh                ;Vorhin wurde einmal zu oft abgezogen: korrigeren.
  499.   ;cmp  al,0                                 ;Soll um 0 Zeilen rotiert werden?
  500.   ;je   NoRotation  <-- überflüssig...                             ;=> Fertig.
  501.   mov  bl,al
  502.   mov  al,dh                                               ;Soll das Window um
  503.   shr  al,1                                               ;mehr als die Hälfte
  504.   cmp  bl,al                                                  ;rotiert werden?
  505.   ja   ScrollReverse                          ;Dann lieber andersrum rotieren.
  506.   clc                                                              ;Params ok,
  507.   ret                                                         ;mit C=0 zurück.
  508. ScrollReverse:  ;Window soll andersrum rotiert werden.
  509.   neg  bl                       ;Rotation-Count an neue Drehrichtung anpassen:
  510.   add  bl,dh                                                   ;BL := DH - BL.
  511.   ret                                                         ;Mit C=1 zurück.
  512. NoRotation:                                            ;Es gibt nichts zu tun?
  513.   add  sp,2                      ;Dann Rückkehradresse auf dem Stack verwerfen
  514.   ret                                  ;und zurück zur übergeordneten Routine.
  515. RotParamCheck ENDP  ;AL destroyed.
  516.  
  517. RotateWindowUp PROC NEAR
  518.   ;BL=NrOfLines, CX=UpperLeft, DX=Size of Window, BH=PageNr.
  519.   call RotParamCheck                           ;Sind die Parameter in Ordnung?
  520.   jc  RotateWindowDown               ;Eignen sie sich besser für "RotateDown"?
  521.   push bx
  522.   push cx
  523.   push bp                                                    ;Register retten.
  524.   push di
  525.   push ds
  526.   push es
  527.   test bh,1                                    ;Welches Page betrifft es denn?
  528.   GetPageArrayIndex 0,si
  529.   cmp  CurVideoMode,8                              ;Sind wir im Graphik-Modus?
  530.   mov  ds,cs:[PageSegment+si]                           ;DS = SEG(ActivePage),
  531.   je   GraphRotation0                  ;Dann andere Rotation-Routine benutzen.
  532.   nop
  533.   DisplayAdress_Text cl,ch                                     ;DisplayAdresse
  534.   shl  ax,1                                              ;mal 2 Bytes pro Char
  535.   mov  si,ax                                       ;=>   DS:SI = StartAdresse.
  536.   mov  bp,+160
  537.   call RotateTextWindow
  538.   jmp  SHORT RotationDone0
  539. GraphRotation0:                                           ;Also Graphik-Modus.
  540.   push dx                        ;Dann erst noch ein weiteres Register retten.
  541.   shl  bl,1                    ;BL (NrOfLines), CH (WinYLo) und DH (WinHeight)
  542.   shl  ch,1                           ;von ZeichenZeilen (je 8 Dots hoch) nach
  543.   shl  dh,1                            ;ScanZeilen (je 4 Dots hoch) umrechnen.
  544.   DisplayAdress_Graph cl,ch
  545.   mov  si,cs:[DispStartTable+si]                                ;DisplayAdress
  546.   add  si,ax                                                     ; + DispStart
  547.   and  si,1FFFh                                               ;nach Begrenzung
  548.   mov  bp,+NrOfDotsX/8                              ;=>  DS:SI = StartAdresse.
  549.   mov  bh,NrOfDotsY/4
  550.   sub  bh,ch      ;BH = Anz ScanLines (je 4 Dots hoch) bis zum BottomOfScreen.
  551.   call RotateBitMap                      ;Erste BitMap (Segment-Offset 0000h),
  552.   call RotateBitMap                             ;zweite BitMap (Offset 2000h),
  553.   call RotateBitMap                                     ;dritte (Offset 4000h)
  554.   call RotateBitMap               ;und vierte (Offset 6000h) seperat rotieren.
  555.   pop  dx
  556. RotationDone0:
  557.   pop  es
  558.   pop  ds
  559.   pop  di                                      ;Gerettete Register zurückholen
  560.   pop  bp
  561.   pop  cx
  562.   pop  bx
  563.   ret                                                             ;und fertig.
  564. RotateWindowUp ENDP  ;AX and SI destroyed.
  565.  
  566. RotateWindowDown PROC NEAR
  567.   ;BL=NrOfLines,  CX=UpperLeft, DX=Size of Window, BH=PageNr.
  568.   call RotParamCheck                           ;Sind die Parameter in Ordnung?
  569.   jc   RotateWindowUp                  ;Eignen sie sich besser für "RotateUp"?
  570.   push bx
  571.   push cx
  572.   push bp
  573.   push di                                                    ;Register retten.
  574.   push ds
  575.   push es
  576.   add  ch,dh                    ;*) Rotation muß in der letzten Zeile beginnen
  577.   dec  ch                                          ;(und nicht in der ersten).
  578.   test bh,1                                  ;Welches ist die betroffene Page?
  579.   GetPageArrayIndex 0,si
  580.   cmp  CurVideoMode,8
  581.   mov  ds,cs:[PageSegment+si]                        ;DS = SEG(ConcernedPage),
  582.   je   GraphRotation1       ;Im GraphikModus andere Rotation-Routine benutzen.
  583.   nop
  584.   cmp  ch,25                    ;ACHTUNG! Durch den Befehl "ADD CH,DH" bei  *)
  585.   jb   NoScreenWrap_Text        ;ist möglicherweise ein ScreenWrap entstanden!
  586.   sub  ch,25
  587. NoScreenWrap_Text:
  588.   DisplayAdress_Text cl,ch                                     ;DisplayAdresse
  589.   shl  ax,1                                              ;mal 2 Bytes pro Char
  590.   mov  si,ax                                        ;=>  DS:SI = StartAdresse.
  591.   mov  bp,-160
  592.   call RotateTextWindow
  593.   jmp  SHORT RotationDone1
  594. GraphRotation1:                                           ;Also Graphik-Modus.
  595.   push dx                        ;Dann erst noch ein weiteres Register retten.
  596.   cmp  ch,NrOfLines
  597.   jb   NoScreenWrap_Graph        ;Dasselbe wie oben, nur diesmal im GraphMode.
  598.   sub  ch,NrOfLines
  599. NoScreenWrap_Graph:
  600.   shl  bl,1
  601.   shl  ch,1                       ;BL, CH und DH in Scan-Lines umrechnen (*2),
  602.   inc  ch                   ;CH dabei an das UNTERE Ende der TextZeile setzen.
  603.   shl  dh,1
  604.   DisplayAdress_Graph cl,ch
  605.   mov  si,cs:[DispStartTable+si]                                ;DisplayAdress
  606.   add  si,ax                                                     ; + DispStart
  607.   and  si,1FFFh                                               ;nach Begrenzung
  608.   mov  bp,-NrOfDotsX/8                              ;=>  DS:SI = StartAdresse.
  609.   mov  bh,ch
  610.   inc  bh                             ;BH = Anz ScanLines bis zum TopOfScreen.
  611.   call RotateBitMap                      ;Erste BitMap (Segment-Offset 0000h),
  612.   call RotateBitMap                             ;zweite BitMap (Offset 2000h),
  613.   call RotateBitMap                                     ;dritte (Offset 4000h)
  614.   call RotateBitMap               ;und vierte (Offset 6000h) seperat rotieren.
  615.   pop  dx
  616. RotationDone1:
  617.   pop  es
  618.   pop  ds
  619.   pop  di
  620.   pop  bp                                     ;Gerettete Register zurückholen.
  621.   pop  cx
  622.   pop  bx
  623.   ret
  624. RotateWindowDown ENDP  ;AX and SI destroyed.
  625.  
  626. RotateTextWindow PROC NEAR
  627.   ;BP = Byte-Distanz zur nächsten Zeile (+ oder - 160 Bytes, je nach Richtung)
  628.   ;DS:SI = Adresse der ersten zu bearbeitenden Zeile.
  629.   ;BL = Um wie viele Zeilen,
  630.   ;DL = wie viele Zeichen pro Zeile, und
  631.   ;DH = wie viele Zeilen rotiert werden sollen.
  632.   cld
  633.   mov  di,cs
  634.   mov  es,di
  635.   mov  di,OFFSET RotateBuffer                         ;[ES:DI] = RotateBuffer.
  636.   mov  al,bl                                             ;AL = MoveLine-Count.
  637.   mov  ch,0
  638.   push si                                   ;"StartAdresse" für später merken.
  639. NextLineIntoBuffer:
  640.   push si
  641.   mov  cl,dl
  642.   rep  movsw
  643.   pop  si
  644.   add  si,bp
  645.   dec  al
  646.   jnz  NextLineIntoBuffer
  647.   nop
  648.   mov  di,ds
  649.   mov  es,di
  650.   pop  di                                               ;ES:DI = StartAdresse.
  651.   mov  al,dh
  652.   sub  al,bl                                             ;AL = MoveLine-Count.
  653. NextLine:
  654.   push si
  655.   push di
  656.   mov  cl,dl
  657.   rep  movsw
  658.   pop  di
  659.   pop  si
  660.   add  di,bp
  661.   add  si,bp
  662.   dec  al
  663.   jnz  NextLine
  664.   nop
  665.   mov  si,cs
  666.   mov  ds,si
  667.   mov  si,OFFSET RotateBuffer                         ;[DS:SI] = RotateBuffer.
  668.   mov  al,bl                                             ;AL = MoveLine-Count.
  669. NextLineFromBuffer:
  670.   push di
  671.   mov  cl,dl
  672.   rep  movsw
  673.   pop  di
  674.   add  di,bp
  675.   dec  al
  676.   jnz  NextLine
  677.   ret
  678. RotateTextWindow ENDP  ;AX, CX, SI, DI, DS, and ES destroyed.
  679.  
  680. RotateBitMap PROC NEAR
  681.   ;BP = Byte-Distanz zur nächsten Zeile (+ oder - 90 Bytes, je nach Richtung)
  682.   ;DS:SI = Adresse der ersten zu bearbeitenden Zeile.
  683.   ;BH = Wie viele Scan-Lines bis zum ScreenWrap.
  684.   ;BL = Um wie viele ScanLines,
  685.   ;DL = wie viele Bytes pro ScanLine, und
  686.   ;DH = wie viele ScanLines rotiert werden sollen.
  687.   ;!!! ACHTUNG, BH muß kleiner oder gleich BL sein !!!
  688.   cld
  689.   push bx                                                    ;Register retten.
  690.   push si
  691.   mov  al,bl                                             ;AL = MoveLine-Count.
  692.   mov  di,cs
  693.   mov  es,di
  694.   mov  di,OFFSET RotateBuffer                         ;[ES:DI] = RotateBuffer.
  695.   push si                             ;BX und "StartAdress" für später merken.
  696. MoveLineIntoBuffer:
  697.   ComputeWrapPos si            ;CX = Wieviele Bytes können OHNE Page-Wrap ver-
  698.   push si                     ;schoben werden, AH = wieviele Bytes sind übrig.
  699.   rep  movsb                       ;Ersten Teil bis zum Page-Wrap verschieben,
  700.   xor  si,si                 ;dann Zeiger auf den Anfang der Page zurücksetzen
  701.   mov  cl,ah                              ;und den Rest der Zeile verschieben.
  702.   rep  movsb
  703.   pop  si
  704.   add  si,bp
  705.   dec  al                               ;Müssen noch Zeilen verschoben werden?
  706.   jnz  MoveLineIntoBuffer
  707.   nop
  708.   mov  di,ds
  709.   mov  es,di
  710.   pop  di                                         ;ES:DI = StartAdress (Dest).
  711.   mov  al,dh
  712.   sub  al,bl                                             ;AL = MoveLine-Count.
  713.   sub  bh,bl                                  ;BH = ScreenWrap-Count (Source).
  714.   inc  bh                                           ;schon mal inkrementieren,
  715.   sub  si,bp
  716. MoveLine:                     ;es wird nämlich gleich wieder dekrementiert --+
  717.   add  si,bp                  ;                                              !
  718.   dec  bh                     ;                                        <-----+
  719.   jnz  NoScreenWrap                         ;Hat ein ScreenWrap stattgefunden?
  720.   mov  bh,NrOfDotsY/4-1                                    ;Dann neu ansetzen:
  721.   test bp,bp                         ;Sind wir am UNTEREN oder am OBEREN Ende?
  722.   js   SetToBottom
  723.   sub  si,ScrSize/4                 ;Am unteren? Dann auf das obere setzen und
  724.   add  di,(8000h-ScrSize)/4               ;DI für neuen DispStart korrigieren.
  725.   jmp  SHORT NoScreenWrap
  726. SetToBottom:
  727.   add  si,ScrSize/4                 ;Am oberen? Dann auf das untere setzen und
  728.   sub  di,(8000h-ScrSize)/4               ;DI für neuen DispStart korrigieren.
  729. NoScreenWrap:
  730.   and  si,1FFFh
  731.   and  di,1FFFh
  732.   ComputeWrapPos si
  733.   test ah,ah                       ;Kommt in dieser SOURCE-Zeile ein Wrap vor?
  734.   jnz  NoSourceWrap
  735.   ComputeWrapPos di              ;Nicht? Dann vielleicht in dieser DEST-Zeile.
  736. NoSourceWrap:
  737.   push si
  738.   push di
  739.   rep  movsb            ;Ersten Teil der Zeile (bis zum PageWrap) verschieben.
  740.   and  si,1FFFh           ;Da ich nicht weiß, WELCHES der beiden IndexRegs den
  741.   and  di,1FFFh      ;Wrap verursacht hat, werden einfach beide zurückgesetzt.
  742.   mov  cl,ah
  743.   rep  movsb
  744.   pop  di
  745.   pop  si
  746.   add  di,bp                                   ;DI eine Zeile weitersetzen und
  747.   dec  al                                      ;MoveLine-Count dekrementieren.
  748.   jnz  MoveLine
  749.   nop
  750.   mov  si,cs
  751.   mov  ds,si
  752.   mov  si,OFFSET RotateBuffer                         ;[DS:SI] = RotateBuffer.
  753. MoveLineFromBuffer:
  754.   ComputeWrapPos di
  755.   push di
  756.   rep  movsb
  757.   xor  di,di
  758.   mov  cl,ah
  759.   rep  movsb
  760.   pop  di
  761.   add  di,bp
  762.   and  di,1FFFh
  763.   dec  bl
  764.   jnz  MoveLineFromBuffer
  765.   nop
  766.   mov  cx,es
  767.   add  cx,200h                     ;DS schon mal auf die nächste BitMap setzen
  768.   mov  ds,cx
  769.   pop  si
  770.   pop  bx                                     ;und Register wieder herstellen.
  771.   ret
  772. RotateBitMap ENDP   ;AX, CX, DI, and ES destroyed, DS:=DS+0200h.
  773.  
  774. ClearWindow PROC NEAR   ;BL=NewAttrib, BH=PageNr, CX=Window Start, DX=WinSize
  775.   push di                                                    ;Register retten.
  776.   test bh,1                             ;In welcher Page soll gelöscht werden?
  777.   GetPageArrayIndex OFFSET(CursPosTable),di
  778.   push [di]                                ;Entsprechende CursorPos pushen und
  779.   mov  [di],cx            ;statt dessen die Pos des Windows dorthin schreiben.
  780.   mov  cl,dl                                              ;"NrOfChars" setzen.
  781.   mov  ch,0
  782. ClearNextLine:
  783.   cmp  dh,0                                         ;War das die letzte Zeile?
  784.   je   ClearDone                                                 ;Dann fertig.
  785.   mov  al,' '
  786.   mov  ah,CurVideoMode            ;(AH muß den momentanen VideoMode enthalten)
  787.   call WriteAttrChar           ;Sonst eine Zeile mit Spaces füllen (=löschen).
  788.   inc  byte ptr [di+1]               ;CursorPos.YPos im BiosSegment eine Zeile
  789.   dec  dh                        ;weitersetzen und ZeilenCount dekrementieren.
  790.   jmp  SHORT ClearNextLine                          ;Nächste Zeile bearbeiten.
  791. ClearDone:
  792.   pop  [di]                                 ;Alte CursorPos wieder herstellen,
  793.   pop  di                                                ;Register zurückholen
  794.   ret                                                  ;und zurück zum Caller.
  795. ClearWindow ENDP  ;AX, CX, DX, and SI destroyed.
  796.  
  797. ComputeDotAdress PROC NEAR  ;CX=XPos, DX=YPos, ZF=PageNr.
  798.   GetPageArrayIndex 0,bx
  799.   mov  es,cs:[PageSegment+bx]                         ;Entsprechende Werte für
  800.   mov  bx,cs:[DispStartTable+bx]               ;Seg und Ofs dieser Page holen.
  801.   ror  dx,1                                            ;YPos von Dots in Scans
  802.   ror  dx,1                                     ;(je 4 Punkte hoch) umrechnen.
  803.   mov  al,90                                     ;ScanNr mal 90 Bytes per Scan
  804.   mul  dl                                         ;ergibt den Offset der Zeile
  805.   add  bx,ax                                         ;(relativ zum DispStart).
  806.   mov  ax,cx
  807.   shr  ax,1                                        ;Jetzt noch den Byte-Offset
  808.   shr  ax,1                                     ;innerhalb der Zeile berechnen
  809.   shr  ax,1                                                      ;(XPos SHR 3)
  810.   add  bx,ax                                      ;und ebenfalls dazuaddieren.
  811.   and  bh,1Fh                                   ;BX auf eine BitMap begrenzen!
  812.   shr  dh,1                               ;Jetzt noch die entsprechende BitMap
  813.   or   bh,dh                              ;über ihre BasisAdresse selektieren.
  814.   and  cl,7
  815.   ret
  816. ComputeDotAdress ENDP  ;ES:BX=DotAdress, CL=BitNr. AX and DX destroyed.
  817.  
  818. HandleBeep PROC NEAR  ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
  819.   cmp  bh,ActivePage                 ;Soll es in einer anderen als der aktiven
  820.   jne  BeepDone                      ;Page piepen? Dann lassen wir das lieber.
  821.   mov  ah,14                                           ;Function "TeletypeOut"
  822.   mov  al,7                                                        ;mit AL=Bel
  823.   pushf                                                         ;des alten (!)
  824.   call dword ptr cs:[SavedInt10Vec]                  ;INT10-Handlers aufrufen.
  825. BeepDone:
  826.   mov  ax,[si]
  827.   ret
  828. HandleBeep ENDP  ;AX=neue CursorPos.
  829.  
  830. HandleReturn PROC NEAR  ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
  831.   mov  ax,[si]
  832.   mov  al,0
  833.   mov  [si],ax
  834.   ret
  835. HandleReturn ENDP  ;AX=neue CursorPos.
  836.  
  837. HandleLinefeed PROC NEAR  ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
  838.   mov  ax,[si]                                    ;CursorPos holen und testen:
  839.   cmp  ah,LastTextLine                        ;Sind wir auf der letzten Zeile?
  840.   je   ScrollOneLineUp                  ;Dann ist eine extra-Behandlung nötig,
  841.   inc  ah                                     ;sonst Cursor einfach eine Zeile
  842.   mov  [si],ax                                        ;tiefer setzen, neue Pos
  843.   ret
  844. ScrollOneLineUp:
  845.   push ax
  846.   push bx
  847.   push cx
  848.   push dx
  849.   mov  ah,CurVideoMode                     ;In der betroffenen DisplayPage das
  850.   call ReadAttrChar                      ;Attrib des Zeichens an der CursorPos
  851.   mov  bl,ah                                   ;holen und mit diesem Attribute
  852.   mov  al,1                                            ;die eine Zeile füllen,
  853.   mov  ah,CurVideoMode                                          ;die entsteht,
  854.   mov  cx,0                                        ;wenn das Window oben links
  855.   mov  dl,byte ptr NrOfColumns                          ;bis ganz unten rechts
  856.   dec  dl                                             ;(also der ganze Screen)
  857.   mov  dh,LastTextLine                                   ;der betroffenen Page
  858.   call ScrollPartOfScreenUp                              ;hochgescrolled wird.
  859.   pop  dx
  860.   pop  cx                                          ;Register wieder herstellen
  861.   pop  bx
  862.   pop  ax
  863.   ret                                                             ;und fertig.
  864. HandleLinefeed ENDP  ;AX=neue CursorPos, SI destroyed.
  865.  
  866. HandleBackspace PROC NEAR  ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
  867.   mov  ax,[si]                                      ;Wo steht der Cursor z.Z.?
  868.   cmp  al,0                ;Auf der ersten Spalte und soll ein Zeichen zurück?
  869.      IF BsLineUp
  870.   je  BackspaceDone                                 ;Dann BackSpace ignorieren
  871.      ELSE
  872.   jne  SetCursorBack
  873.   cmp  ah,0                                                             ;oder,
  874.   je   BackspaceDone                ;wenn Cursor nicht schon in Home-Position,
  875.   dec  ah                                                    ;eine Zeile höher
  876.   mov  al,byte ptr NrOfColumns                 ;auf das letzte Zeichen setzen.
  877. SetCursorBack:
  878.      ENDIF
  879.   dec  al
  880.   mov  [si],ax                                ;Neue Cursor-Position speichern.
  881. BackspaceDone:
  882.   ret
  883. HandleBackspace ENDP  ;AX=neue CursorPos.
  884.  
  885. WriteOneChar PROC NEAR  ;AL=Char, BL=Attrib, BH=PageNr, [DS:SI]=CursorPos.
  886.   cmp  al,7
  887.   je   HandleBeep                                                        ;Bel,
  888.   cmp  al,13
  889.   je   HandleReturn                                                       ;Cr,
  890.   cmp  al,10
  891.   je   HandleLineFeed                                                  ;Lf und
  892.   cmp  al,8
  893.   je   HandleBackspace                                  ;Bs separat behandeln,
  894.   push cx                                                ;alle anderen Zeichen
  895.   push si                                       ;als 'Printables' verarbeiten:
  896.   mov  cx,1                                                       ;Ein Zeichen
  897.   mov  ah,CurVideoMode                                      ;im aktuellen Mode
  898.   call WriteAttrChar                                 ;mit Attribute schreiben,
  899.   pop  si
  900.   pop  cx
  901.   mov  ax,[si]                                     ;Wo steht der Cursor JETZT?
  902.   inc  al
  903.   mov  [si],ax                          ;Ein Zeichen weiter nach rechts setzen
  904.   cmp  al,byte ptr NrOfColumns            ;und testen: Sind wir noch innerhalb
  905.   jne  WriteOneCharDone                         ;der Zeile? Dann ist's ja gut.
  906.   call HandleReturn                               ;Sonst Cursor auf den Anfang
  907.   call HandleLineFeed                              ;der nächsten Zeile setzen.
  908. WriteOneCharDone:
  909.   ret                    ;Achtung! CursorPos wird NICHT an den 6845 geschickt!
  910. WriteOneChar ENDP  ;AX=neue CursorPos, SI destroyed.
  911.  
  912. SendStringToPrinter PROC NEAR  ;[CS:SI]=PascalString.
  913.   cld
  914.   lods byte ptr cs:[si]                                        ;Längenbyte des
  915.   mov  cl,al                                                    ;PascalStrings
  916.   mov  ch,0                                                    ;nach CX holen.
  917.   clc
  918.   jcxz SendStringDone               ;String leer? Dann fertig, mit C=0 zurück.
  919.   mov  dl,cs:PrinterNr
  920.   mov  dh,0                                       ;Sonst PrinterNummer nach DX
  921. SendByteLoop:
  922.   lods byte ptr cs:[si]              ;und in einer Schleife ein Zeichen holen,
  923.   mov  ah,0
  924.   int  17h                                             ;mittels Bios ausgeben,
  925.   and  ah,00111001b                          ;Status testen (OutOfPaper=False,
  926.   cmp  ah,00010000b          ;Selected=True, IOError=False und TimeOut=False?)
  927.   loope SendByteLoop      ;Status ok? Dann nächstes Zeichen (falls vorhanden).
  928.   clc                                 ;Schleife abgebrochen, woran lag's denn?
  929.   jz   SendStringDone       ;Bloß Stringende erreicht? Dann war's erfolgreich.
  930.   stc                            ;Sonst lag es wohl am Status. Mit C=1 zurück.
  931. SendStringDone:
  932.   ret
  933. SendStringToPrinter ENDP  ;AX, CX, DX, and SI destroyed. C=1 wenn Fehler.
  934.  
  935. PrintTextScreen PROC NEAR  ;AL=ActivePage
  936.   push bx
  937.   push cx
  938.   push dx                                                    ;Register retten.
  939.   push si
  940.   test al,1                                       ;Welche Page ist denn aktiv?
  941.   GetPageArrayIndex 0,si                ;Diese Page soll auch gedruckt werden.
  942.   push [CursPosTable+si]                          ;Momentane CursorPos merken!
  943.   mov  ds,cs:[PageSegment+si]
  944.   mov  si,OFFSET PrnTextInit                          ;TextHardcopy-InitString
  945.   call SendStringToPrinter                              ;zum Drucker schicken.
  946.   jc   PrintTextFinished                       ;Fehler? => Hardcopy abbrechen.
  947.   mov  si,0                                              ;[DS:SI]=Active Page.
  948.   mov  bx,0                                       ;LineCounter initialisieren.
  949. PrintTextLineLoop:
  950.   mov  ax,bx                                        ;Cursor auf den Anfang der
  951.   call UpdateCursorPos                          ;z.Z. gedruckten Zeile setzen.
  952.   mov  cx,80
  953.   mov  dl,0
  954.   mov  dh,cs:PrinterNr                                     ;DX=Printer-Number.
  955.   cld
  956. PrintTextCharLoop:
  957.   lods byte ptr ds:[si]                       ;Erstes Zeichen der Zeile holen,
  958.   inc  si                                            ;(Attribute überspringen)
  959.   mov  ah,0
  960.   int  17h                                           ;und an Drucker schicken.
  961.   and  ah,00111001b
  962.   cmp  ah,00010000b
  963.   loope PrintTextCharLoop              ;Solange, bis Zeile zuende oder Fehler.
  964.   jnz  PrintTextFinished                    ;Fehler (Drucker offline oder so)?
  965.   cmp  cs:PrtScrActive,True            ;Oder PrtScr durch erneuten Tastendruck
  966.   jne  PrintTextFinished                 ;abgebrochen? Dann vorzeitig beenden.
  967.   inc  bh
  968.   cmp  bh,25
  969.   jne  PrintTextLineLoop
  970. PrintTextFinished:
  971.   mov  si,OFFSET PrnTextExit                          ;TextHardcopy-ExitString
  972.   call SendStringToPrinter                              ;zum Drucker schicken.
  973.   pop  ax                                        ;Alte CursorPos wieder holen,
  974.   pop  si
  975.   pop  dx                                      ;Register wieder herstellen und
  976.   pop  cx
  977.   pop  bx
  978.   call UpdateCursorPos           ;Cursor auf seine alte Position zurücksetzen.
  979.   ret
  980. PrintTextScreen ENDP  ;AX and DS destroyed.
  981.  
  982. PrintGraphScreen PROC NEAR  ;AL=ActivePage
  983.   push bx
  984.   push cx
  985.   push dx                                                    ;Register retten.
  986.   push si
  987.   push di
  988.   test al,1
  989.   GetPageArrayIndex 0,di                ;Welche Page soll den gedruckt werden?
  990.   mov  ds,cs:[PageSegment+di]
  991.   mov  di,cs:[DispStartTable+di]               ;[DS:DI]=DispStart dieser Page.
  992.   mov  si,OFFSET PrnGraphInit                        ;GraphHardcopy-InitString
  993.   call SendStringToPrinter                              ;zum Drucker schicken.
  994.   jc   PrintGraphFinished                      ;Fehler? => Hardcopy abbrechen.
  995.   mov  bl,NrOfLines                               ;LineCounter initialisieren.
  996. PrintGraphLineLoop:
  997.   mov  si,OFFSET PrnLineStart
  998.   call SendStringToPrinter             ;LineStart-String zum Drucker schicken.
  999.   mov  cx,NrOfChars                        ;Counter für "CharsPerLine" setzen.
  1000. PrintGraphCharLoop:
  1001.   cld
  1002.   push cx                                                   ;CharCount merken.
  1003.   mov  bh,2                       ;Jetzt werden 2 Scans (= 8 Dots = 1 Zeichen)
  1004. ConvertNextByte:
  1005.   mov  si,OFFSET PrtScr8x8Buffer    ;konvertiert und in den Buffer übertragen:
  1006.   inc  si                                           ;(LängenByte überspringen)
  1007.   mov  al,[di]                     ;Ein Byte aus dem Bildschirmspeicher holen,
  1008.   xor  al,0FFh                       ;invertieren (für Druck schwarz auf weiß)
  1009.   mov  cx,8                                 ;und die 8 Bits einzeln verteilen:
  1010. ConvertNextBit:
  1011.   shl  al,1                       ;MSB des Graphik-Bytes in den Carry schieben
  1012.   rcl  byte ptr cs:[si],1             ;und von dort in das erste Drucker-Byte,
  1013.   inc  si                              ;dann nächstes Bit in das nächste Byte.
  1014.   loop ConvertNextBit
  1015.   add  di,2000h                   ;Jetzt ist das nächste GraphikByte dran, das
  1016.   jno  ConvertNextByte        ;liegt eine Zeile tiefer in der nächsten BitMap,
  1017.   add  di,NrOfChars             ;aber nach 4 BitMaps einen Scan tiefer setzen.
  1018.   and  di,1FFFh                                  ;Dabei den PageWrap beachten.
  1019.   dec  bh
  1020.   jnz  ConvertNextByte                          ;Schon beide Scans bearbeitet?
  1021.   mov  si,OFFSET PrtScr8x8Buffer               ;Dann die konvertierten 8 Bytes
  1022.   call SendStringToPrinter                        ;jetzt zum Drucker schicken.
  1023.   add  di,-2*NrOfChars+1        ;ScreenPointer auf das nächste Zeichen setzen,
  1024.   pop  cx                                              ;CharCount wieder holen
  1025.   loop PrintGraphCharLoop                    ;und nächstes Zeichen bearbeiten.
  1026.   mov  si,OFFSET PrnLineEnd
  1027.   call SendStringToPrinter               ;LineEnd-String zum Drucker schicken.
  1028.   jc   PrintGraphFinished                       ;Fehler (z.B. Printer Offline)
  1029.   cmp  cs:PrtScrActive,True                ;oder PrtScr durch erneuten Tasten-
  1030.   jne  PrintGraphFinished                    ;druck abgebrochen? Dann beenden.
  1031.   add  di,NrOfChars             ;Sonst ScreenPointer eine Zeile tiefer setzen,
  1032.   dec  bl                                          ;ZeilenCount dekrementieren
  1033.   jnz  PrintGraphLineLoop                          ;und nächste Zeile drucken.
  1034. PrintGraphFinished:
  1035.   mov  si,OFFSET PrnGraphExit                        ;GraphHardcopy-ExitString
  1036.   call SendStringToPrinter                              ;zum Drucker schicken.
  1037.   pop  di
  1038.   pop  si
  1039.   pop  dx                                         ;Register wieder herstellen.
  1040.   pop  cx
  1041.   pop  bx
  1042.   ret
  1043. PrintGraphScreen ENDP  ;AX and DS destroyed.
  1044.